#include "Range.h"

Range::Range(int x, int y) {
    start = x;
    end = y;
    Populate();
}

Range::Range() {
    start = NULL;
    end = NULL;
}

Range::~Range(void) {}

void Range::updateEnds(int x, int y) {
    if (start == NULL && end == NULL) {
        start = x;
        end = y;
    } else {
        if (x < start) start = x;
        if (y > end) end = y;
    }
}

void Range::Populate() {
    for (int i = start; i <= end; i++) r.push_back(i);
}

void Range::Print() {
    std::cout << "Range:" << std::endl;
    for (int i = start; i <= end; i++) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
}

int Range::getStart() {
    return start;
}

int Range::getEnd() {
    return end;
}

bool Range::Contains(int x) {
    for (std::vector<int>::iterator it = r.begin(); it != r.end(); ++it) {
        if (*it == x) return true;
    }
    return false;
}

bool Range::Contains(int x, int y) {
    int count = 0;
    int total = 1; // Account for including both ends of the range

    if (x > y) return false; // Invalid syntax
    else if (x == y) return Contains(x);
    else if (abs(y) == abs(x)) total += 2 * y;
    else total += y - x;

    for (std::vector<int>::iterator it = r.begin(); it != r.end(); ++it) {
        if (*it >= x && *it <= y) count++;
    }

    if (total == count) return true;
    else return false;
}

void Range::Add(int x, int y) {
    if (r.size() == 0) {
        updateEnds(x, y);
        Populate();
        return;
    }

    updateEnds(x, y);
    for (int i = start; i <= end; i++) {
        if (!Contains(i)) r.insert(std::lower_bound(r.begin(), r.end(), i), i);
    }
}

void Range::Remove(int x, int y) {
    std::vector<int>::iterator it = r.begin();
    while (it != r.end()) {
        if (*it >= x && *it <= y) {
            // it becomes inacessible after passed to erase but
            // erase returns an iterator pointing to the next value
            it = r.erase(it);
        } else {
            ++it;
        }
    }

    // Update start and end. End has to be decremented since it points
    // to the iterator after the last value, aka the past-the-end element
    start = *r.begin();
    end = *--r.end();
}
